#pragma once
#include <iostream>
#include <functional>
#include <unistd.h>
#include<cstring>
#include "Log.hpp"
#include "channel.hpp"
#include "User.hpp"

typedef std::function<void(int)> func_t;

// JOIN 加入频道
#define JOIN "JOIN" 
// CREATE 创建频道
#define CREATE "CREATE" 
 
#define NICK "NICK" 

// QUIT 退出频道
#define QUIT "QUIT" 


namespace chatroom
{
     void IOServer(int sock,UserManage* um,UserManage* mc);
    // {
    //     char buff[1024] = {0};
    //     for (;;)
    //     {
    //         // 读数据
    //         int n = read(sock, buff, sizeof buff - 1);
    //         if (n > 0)
    //         {
    //             string buffstr = buff; 
    //             //解析IRC???


    //             /*
    //             buff[n] = 0;
    //             std::string message = "[Server Echo] :";
    //             message += buff;
    //             std::cout << "clinet : " << buff << std::endl;
    //             write(sock, message.c_str(), message.size()); // 写数据
    //             */
    //         }
    //         else if (n == 0)
    //         {
    //             logMessage(NORMAL, "client quit... me too");
    //             break;
    //         }
    //         else
    //         {
    //             logMessage(ERROR, "read failed..... sock : %d", sock);
    //             break;
    //         }
    //     }
    //     close(sock);
    // }

    class Task
    {
    public:
        Task() {}
        Task(int sock, UserManage* um,ManageChannel* mc) : _sock(sock), 
        _um(um),_mc(mc),_is_load(false) {
            logMessage(DEBUG,"任务创建成功，sock ：%d" , _sock);
        }


        void operator()()
        {
            char buff[1024] = {0};
            for (;;)
            {
                // 读数据
                memset(buff,0,sizeof buff);
                int n = read(_sock, buff, sizeof buff - 1);
                if (n > 0)
                {
                    int i = -1;
                    std::string buffstr = buff; 
                    logMessage(DEBUG,"收到客户端消息[%s]",buff);
                    int pos = buffstr.find(" "); 
                    if(pos == std::string::npos && buffstr != QUIT)
                    {
                        //没有空格信息发送
                        SendBroadcast(buffstr,true);
                    }
                    else if(buffstr.substr(0,pos) == JOIN)
                    {
                        //加入频道消息
                        while(buffstr[pos] == ' ')pos++;
                        Join(buffstr.substr(pos)); 
                    }else if(buffstr.substr(0,pos )== CREATE)
                    {
                        //创建频道
                        while(buffstr[pos] == ' ')pos++;
                        Create(buffstr.substr(pos)); 
                    }else if (buffstr.substr(0, pos) == NICK)
                    {
                        //NICK登陆
                        while(buffstr[pos] == ' ')pos++;
                        Nick(buffstr.substr(pos)); 
                    }else if(buffstr == QUIT)
                    {
                        //QUIT退出
                        i = Quit(); 
                    }else
                    {
                        //普通信息
                        SendBroadcast(buffstr,true);
                    }

                    //客户端退出了
                    if(i == 0) break;
                }
                else if (n == 0)
                {
                    logMessage(NORMAL, "client quit... me too");
                    //移除用户,一直调用QUIT直到返回0
                    //对端强制关闭，需要把用户移除
                    _mc->RemoveUserFromChannel(&_user);
                    _um->RemoveUser(_user.GetId());
                    break;
                }
                else
                {
                    logMessage(ERROR, "read failed..... sock : %d", _sock);
                    break;
                }
            }
            if(_sock >= 0)
            close(_sock);
            //_func(_sock,_um,_mc);
        }
    private:
        //客户端加入服务器请求
        void Join(const std::string& joinmessage)
        {  
            if(!_is_load)
            {
                SendClient("您还未登陆，登陆请输入# NICK 名称");
                return;
            }
            if(_user.IsJoin()) return  SendClient("你已经在频道" + std::to_string(_user.GetRid()) + "中了！");
            int i = 0 ;
            //提取JOIN后面的信息，必须是全数字
            for(auto& e : joinmessage)
            {
                if(e >= '0' && e <= '9')
                    i = i * 10 + (e - 48); 
                else return SendClient("频道号不存在");
            }
            logMessage(DEBUG,"正在查找%d房间....",i);
            Channel* channel = _mc->FindChannel(i); 
            logMessage(DEBUG,"房间%d查找完毕........",i);
            if(channel == nullptr)
            {
                //频道号不存在
                logMessage(DEBUG,"加入频道%d不存在！",i);
                return SendClient("频道号不存在");
            }
            
            //频道存在，加入成功！
            if(_mc->AddUserToChannel(channel->GetRid(),&_user))
            {
                logMessage(DEBUG,"加入频道%d成功！",i);
                //SendClient("加入频道 :" + std::to_string(channel->GetRid()) + "成功！");
                _user.SetRid(i);
                _user.SetIsJoin(true);
                SendBroadcast(_user.GetName() + "加入频道!",false);
                return;
            }
            logMessage(DEBUG,"未知异常....");

            SendClient("未知异常....");
        }

        //创建频道
        void Create(const std::string& message)
        {
            //检测频道是否存在
      
            //检测频道是否是全数字，且在6位数 
           if(message.size() == 0) return SendClient("请输入频道号"); 
            int i = 0 ;
            for(auto& ch : message)
            {
                if(ch >= '0' && ch <= '9')
                    i = i * 10 + (ch - 48); 
                else return SendClient("频道需要是一个纯数字");
            }
            Channel* ch = _mc->FindChannel(i);
            if(ch != nullptr) 
                return   SendClient("该频道已经创建过了，请换一个试试");
            //频道最大数量50，可以自己设置...
            SendClient("创建频道成功！");
            _mc->CreateChannel(50,i); 
            logMessage(DEBUG,"创建房间成功！");
            _user.SetRid(i);
            logMessage(DEBUG,"设置用户的RID%d",_user.GetRid());

            //创建成功后把当前用户加入房间
            _user.SetIsJoin(true);
            logMessage(DEBUG,"设置用户的IsJoin");

            logMessage(DEBUG,"把user添加进频道");
            _mc->AddUserToChannel(i,&_user);

        }

        //登陆请求
        void Nick(const std::string& name)
        {
            _user.SetName(name);
            _user.SetSock(_sock);
            _user.SetUid(_um->GetIdx());
            logMessage(DEBUG,"添加用户... sock = %d",_sock);
           bool flag =  _um->AddUser(name,&_user,_sock);
            logMessage(DEBUG,"添加用户成功... sock = %d",_user.GetSock());

           if(flag == false)
           {
                SendClient("登陆失败，未知原因");
                return;
           }
           SendClient("登陆成功！");
            _is_load = true;

        }

        //用户退出,返回0退出客户端，返回1退出频道
        int Quit()
        {
            logMessage(DEBUG,"用户正在退出....");
            //不在频道，退出客户端
            if(!_user.IsJoin())
            {
                SendClient("正在为你关闭客户端.....");
                logMessage(DEBUG,"移除用户....");
                _um->RemoveUser(_user.GetId());
                return 0 ;
            }
            logMessage(DEBUG,"用户在频道");
            //在频道，退出频道
            SendBroadcast(_user.GetName() + "退出频道！",false);
            logMessage(DEBUG,"把用户移除频道.....");
            _mc->RemoveUserFromChannel(&_user);
            logMessage(DEBUG,"移除完毕，设置用户状态.....");
            _user.SetIsJoin(false);
            return 1;
        }

        //单独给客户端发送
        void SendClient(const std::string& send_message)
        {
            if(send_message.size() > 0 )
            {
                write(_sock,send_message.c_str(),send_message.size());
            }
        }
        //消息广播
        void SendBroadcast(const std::string& send_message,bool isname)
        {
            //还没有登陆
            if(!_is_load) return SendClient("你还没有登陆聊天室，输入# NICK 名称 进行登陆");
            
            //还没加入频道
            if(!_user.IsJoin())  return SendClient("你还没有加入频道，输入# JOIN id 加入频道");
            
            //获取用户所在频道
            Channel* channel = _mc->FindChannel(_user.GetRid());
            if(channel == nullptr)
            {
                SendClient("你加入的频道还未创建,请输入# CREATE id 创建频道");
                return;
            }
            logMessage(DEBUG,"正在广播消息....");
            if(isname)
                channel->Broadcast(send_message,&_user); //频道广播
            else  channel->Broadcast(send_message,nullptr);
        }
        

    public:
        int _sock;
        func_t _func;
        UserManage* _um; 
        ManageChannel* _mc;
        User _user;
        bool _is_load;
    };
}